#ifndef _UDP_SERVER_H_
#define _UDP_SERVER_H_

#include <string>
#include <mutex>
#include <thread>
#include "event2/event.h"
#ifdef _WIN32
    #include <winsock2.h>
#else
    #include <netinet/in.h>
#endif

#define UDP_SERVER_BUF_SIZE (512)

class UdpServer
{
public:
    using ReadHandler = void (*)(struct sockaddr_in from, unsigned char * buf, int size, void * arg);/* 设置读取数据回调函数 */
public:
    UdpServer();
    virtual ~UdpServer();
public:
    bool init(const std::string & addr, int port);       /* 初始化 */
    bool start();                                        /* 启动监听新连接 */
    bool stop();                                         /* 停止监听新连接 */
    bool setReadHandler(const ReadHandler & readCb, void * arg = nullptr); /* 设置读到报警消息的回调函数 */
private:
    UdpServer(const UdpServer &) = delete;            /* 禁止外部调用拷贝构造函数 */
    UdpServer& operator = (const UdpServer&) = delete;/* 禁用赋值操作符 */
private:
    bool deInit();                                                            /* 释放资源 */
    void closeSocket(int sockfd);
    static void readCallBack(evutil_socket_t sockfd, short event, void * arg);/* bufferevent读回调函数 */
    static void * dispatchThread(void * arg);                                 /* dispatch线程函数 */
private:
    std::string  m_addr;    /* ip */
    int m_port = 0;         /* 端口号 */
#ifdef _WIN32
    SOCKET m_sockfd = -1;
#else
    int m_sockfd = -1;
#endif
    event_base* m_base = nullptr;
    struct event * m_event = nullptr;
    ReadHandler m_readHandler = nullptr; /* 用于存放回调函数指针 */
    void * m_callbackArg = nullptr;

    std::thread *m_thread = nullptr; /* dispatch线程 */
    bool m_isRunning = false;        /* 运行标志 */
    bool m_isInited = false;         /* 初始化标志 */
    std::mutex m_mutex;
};

#endif
